package cate.game.pvp.pointrace;

import cate.game.framework.ModuleMan;


import cate.game.pvp.pointrace.data.PointRaceKV;
import cate.game.pvp.pointrace.handler.*;
import cate.game.pvp.pointrace.simulator.*;
import cate.game.pvp.pointrace.timer.PointRaceTimerTask;
import cate.game.pvp.pointrace.timer.PointRaceTimerTask.Settings;
import com.google.common.collect.Lists;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;

import static cate.game.pvp.pointrace.timer.PointRaceTimerTask.DEFAULT_SETTINGS_CONSUMER;

public class PointRaceSimulatorManager extends ModuleMan
        implements PointRaceTimerTask.SettingsConsumerSelector {

    private final Supplier<PointRaceKV> kvSupplier;
    private final Supplier<PointRaceRankRwdOperation> rankRwdOperationSupplier;
    private final Supplier<PointRaceRankHandler> rankHandlerSupplier;
    private final Supplier<PointRaceExcelQueryOperation> excelQueryOperationSupplier;
    private final Supplier<PointRacePsOperation> psOperationSupplier;
    private final Supplier<PointRaceChallenge> challengeSupplier;

    public PointRaceSimulatorManager(
            Supplier<PointRaceKV> kvSupplier,
            Supplier<PointRaceRankRwdOperation> rankRwdOperationSupplier,
            Supplier<PointRaceRankHandler> rankHandlerSupplier,
            Supplier<PointRaceExcelQueryOperation> excelQueryOperationSupplier,
            Supplier<PointRacePsOperation> psOperationSupplier,
            Supplier<PointRaceChallenge> challengeSupplier) {
        this.kvSupplier = Objects.requireNonNull(kvSupplier);
        this.rankRwdOperationSupplier = Objects.requireNonNull(rankRwdOperationSupplier);
        this.rankHandlerSupplier = Objects.requireNonNull(rankHandlerSupplier);
        this.excelQueryOperationSupplier = Objects.requireNonNull(excelQueryOperationSupplier);
        this.psOperationSupplier = Objects.requireNonNull(psOperationSupplier);
        this.challengeSupplier = Objects.requireNonNull(challengeSupplier);
        this.simulatorSelector = new BothPointRaceSimulatorSelector(this::buildSimulatorList);
    }

    private final PointRaceSimulatorSelector simulatorSelector;

    @Override
    public Consumer<Settings> select(Settings settings) {
        return Optional.of(settings)
                .map(this.simulatorSelector::select)
                .map(PointRaceSimulator::getSettingsConsumer)
                .orElse(DEFAULT_SETTINGS_CONSUMER);
    }

    private List<PointRaceSimulator> buildSimulatorList() {
        return Lists.newArrayList(
                new BothPointRaceControlSimulator(
                        this.kvSupplier,
                        this.psOperationSupplier,
                        this.challengeSupplier
                ),
                new BothPointRaceRwdSimulator(
                        this.kvSupplier,
                        this.rankRwdOperationSupplier,
                        this.rankHandlerSupplier,
                        this.excelQueryOperationSupplier
                )
        );
    }

    @Override
    public void initDependent() throws Exception {
        // no-op
    }
}
